import matplotlib.pyplot as plt
import numpy as np

# 拉格朗日多项式计算程序
def lagrange_interpolation(x, x_values, y_values):
    """
        拉格朗日插值法

        参数:
            x_values : list or array, 已知节点的 x 坐标
            y_values : list or array, 已知节点的 y 值
            x : float, 需要插值的点

        返回:
            插值结果 f(x)
        """
    n = len(x_values)
    result = 0

    for i in range(n):
        term = y_values[i]
        for j in range(n):
            if i != j:
                term *= (x - x_values[j]) / (x_values[i] - x_values[j])
        result += term

    return result


# 给定的数据点
x_values = [0.5, 1,  1.5, 2,  2.5, 3,  3.5, 4, 4.5, 5 ]
y_values = [2.596764, 3.250621, 2.870067, 2.289152, 2.479532, 3.636543, 4.974973, 5.425024, 4.595602, 3.130625]

# 测试插值
x_1 = 1.85
y_1 = lagrange_interpolation(x_1, x_values, y_values)
print(f"f({x_1}) = {y_1}")

# 插值范围 1.85 到 3.25
x_2 = 3.25
y_2 = lagrange_interpolation(x_2, x_values, y_values)
print(f"f({x_2}) = {y_2}")


# 创建插值范围 (从 0.5 到 3.5)
x = np.linspace(min(x_values), max(x_values), 50)
y = np.array([lagrange_interpolation(xi, x_values, y_values) for xi in x])

# 绘制曲线
plt.figure()
plt.plot(x, y, 'b-', linewidth=2)
plt.plot(x, y, 'ro', markersize=4)  # 标记数据点
plt.grid(True)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('Lagrange Interpolation')
plt.legend([])
plt.show()

#数据验证-- 残差函数R(x)
# 假设的真实函数 f(x) = 2x^2 - 3x + 4
def true_function(x):
    return 2 * x**2 - 3 * x + 4

x_train = np.linspace(1,10, 50)
# 计算真实函数值
y_train = true_function(x_train)
# 计算拉格朗日插值结果
x_test = np.linspace(1,10, 15)
y_interp = lagrange_interpolation(x_test, x_train, y_train)
y_true = true_function(x_test)
# 计算残差 R(x)
residual = y_true - y_interp
res = np.column_stack((x_test, residual))
print(res)
